package edu.upf.opencities.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import edu.upf.opencities.datamodel.Entry;
import edu.upf.opencities.datamodel.Extras;
import edu.upf.opencities.datamodel.Message;
import edu.upf.opencities.datamodel.OSNEntry;
import edu.upf.opencities.datamodel.OSNService;
import edu.upf.opencities.datamodel.ObjectFactory;
import edu.upf.opencities.datamodel.Resource;
import edu.upf.opencities.datamodel.Resources;
import edu.upf.opencities.manager.ServiceManager;

/**
 * 
 * @author Manu (manuelpalacin@gmail.com)
 *
 * REST (Only Jersey) (CXF: http://cxf.apache.org/docs/jaxrs-services-description.html#JAXRSServicesDescription-Basicexample)
 * WADL descriptor: http://[SERVER_ADDRESS]:[SERVER_PORT]/OSN/rest/application.wadl
 * 
 * REST request
 * http://[SERVER_ADDRESS]:[SERVER_PORT]/OSN/rest/[ws_path_name]/[method_path_name]/{param1}/.../{paramN}
 * 
 */

@Service("service")
@Path("/service")
public class ServiceService {

	@Autowired
	private ServiceManager serviceManager;
	@Autowired
	private UserService userService;
	@Autowired
	private ObjectFactory objectFactory;
	
	/**
	 * Service register service method
	 * 
	 * @param IdOSNService
	 * @param mail
	 * @param serviceName
	 * @param servicePassword
	 * @param owner
	 * @param description
	 * @param updatePeriod
	 * @param section
	 * @param longitude
	 * @param latitude
	 * @param tagList
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/registerService/manuel.palacin@upf.edu/s3cr3t/TempService/s3cr3t/UPF/TemperatureService/10min/Environmental/2.5E/42.2N/cold,hot
	@GET
	@Path("/registerService/{mail}/{userPassword}/{serviceName}/{servicePassword}/{owner}/" +
			"{description}/{updatePeriod}/{section}/{latitude}/{longitude}/{tags}")
	public Message registerService (
			@PathParam("mail")String mail, @PathParam("userPassword")String userPassword,
			@PathParam("serviceName")String serviceName, 
			@PathParam("servicePassword")String servicePassword, @PathParam("owner")String owner, 
			@PathParam("description")String description, @PathParam("updatePeriod")String updatePeriod, 
			@PathParam("section")String section, 
			@PathParam("latitude")String latitude, @PathParam("longitude")String  longitude,
			@PathParam("tags")String tagsRAW){

		if (userService.loginUser(mail, userPassword).getContent().equals("true")){
			//we process the received TAGs separated with ","
			String input = tagsRAW;
			String delimiter = ",";
			String[] tags = input.split(delimiter);
			List<String> tagList = new ArrayList<String>();
			for (String tag : tags) {
				tagList.add(tag);
			}
			
			String idOSNService = serviceManager.registerService(mail, serviceName, 
					servicePassword, owner, description, 
					updatePeriod, section, latitude, longitude, tagList);
			
			return createMessage(idOSNService);
		} else {
			return createMessage("Please register into the system");
		}
	}
	
	/**
	 * Service delete service method
	 * 
	 * @param idOSNService
	 */
	//http://localhost:8080/OSN/rest/service/deleteService/manuel.palacin@upf.edu/s3cr3t/8c3a7780-f440-176d-a019-080027769f33
	@GET
	@Path("/deleteService/{mail}/{userPassword}/{idOSNService}")
	public Message deleteService( 
			@PathParam("mail")String mail, @PathParam("userPassword")String userPassword,
			@PathParam("idOSNService")String idOSNService ){
		
		if (userService.loginUser(mail, userPassword).getContent().equals("true")){
			serviceManager.deleteService( idOSNService);
			return createMessage("Delete service done") ;
		} else {

			return createMessage("Please register into the system");
		}
	}
	
	
	/**
	 * Service get service method
	 * 
	 * @param IdOSNService
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getService/f9553500-f619-176d-b6d4-080027769f33
	@GET
	@Path("/getService/{idOSNService}")
	public OSNService getService (  @PathParam("idOSNService")String idOSNService ){
		
		return serviceManager.getService(idOSNService);
	}
	
	/**
	 * Service get services method by mail owner
	 * 
	 * @param mail
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getServicesByMail/manuel.palacin@upf.edu
	@GET
	@Path("/getServicesByMail/{mail}")
	public List<OSNService> getServicesByMail( @PathParam("mail")String mail ){
		
		return serviceManager.getServicesByMail(mail);
	}
	
	/**
	 * Service get services method by section
	 * 
	 * @param section
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getServicesBySection/Environmental
	@GET
	@Path("/getServicesBySection/{section}")
	public List<OSNService> getServicesBySection(  @PathParam("section")String section ){
		
		return serviceManager.getServicesBySection(section);
	}
	
	/**
	 * Service get services method by tag
	 * 
	 * @param tag
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getServicesByTag/cold
	@GET
	@Path("/getServicesByTag/{tag}")
	public List<OSNService> getServicesByTag( @PathParam("tag")String tag ){
		return serviceManager.getServicesByTag(tag);
	}
	
	/**
	 * Service add entry method
	 * 
	 * @param IdOSNService
	 * @param IdOSNEntry
	 * @param timeStamp
	 * @param value
	 */
	//http://localhost:8080/OSN/rest/service/addEntry/c5c05200-fad4-176d-95de-080027769f33/s3cr3t/2011-07-09T15:38:45.834Z/22degrees/2.5E/42.2N
	@GET
	@Path("/addEntry/{idOSNService}/{servicePassword}/{timeStamp}/{value}/{longitude}/{latitude}")
	public Message addEntry( 
			@PathParam("idOSNService")String idOSNService, @PathParam("servicePassword")String servicePassword,
			@PathParam("timeStamp") String timeStampRAW, 
			@PathParam("value")String value, 
			@PathParam("longitude")String longitude, @PathParam("latitude")String latitude ){

		if (loginService(idOSNService, servicePassword).getContent().equals("true")){
			//First we convert the date string (timeStampRAW) to XML gregorian calendar
			XMLGregorianCalendar xmlgcal = null;
			try {
	    		GregorianCalendar gcal = new GregorianCalendar();
	    		String dateString = timeStampRAW; //"Example: 2011-07-09T15:38:45.834Z"
	    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
				Date date = sdf.parse(dateString);
	    		gcal.setTime(date);
	    		xmlgcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
			} catch (ParseException e) {
				e.printStackTrace();
				return  createMessage("ERROR: bad timeStamp format");
			} catch (DatatypeConfigurationException e) {
				e.printStackTrace();
				return createMessage("ERROR: bad timeStamp format");
			}
			return createMessage(serviceManager.addEntry(idOSNService, xmlgcal, value, longitude, latitude));
		
		} else {
			return createMessage("Incorrect service credentials");
		}
	}
	
	
	/**
	 * Service get entries from service method
	 * 
	 * @param idOSNService
	 * @param numEntries
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getEntriesFromService/c5c05200-fad4-176d-95de-080027769f33/7
	@GET
	@Path("/getEntriesFromService/{idOSNService}/{numEntries}")
	public List<OSNEntry> getEntriesFromService( 
			@PathParam("idOSNService")String idOSNService, @PathParam("numEntries")String numEntriesRAW ){
		//First we convert the numEntries from a string to int
		int numEntries = Integer.parseInt(numEntriesRAW);
		
		return serviceManager.getEntriesFromService(idOSNService, numEntries);
	}
	
	
	/**
	 * Service get Last entry method
	 * 
	 * @param idOSNService
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/getLastEntry/c5c05200-fad4-176d-95de-080027769f33
	@GET
	@Path("/getLastEntry/{idOSNService}")
	public OSNEntry getLastEntry( @PathParam("idOSNService")String idOSNService ){
		
		return serviceManager.getLastEntry(idOSNService);
	}
	
	/**
	 * Service add Twitter user method
	 * 
	 * @param idOSNService
	 * @param consumerKey
	 * @param consumerSecret
	 * @param token
	 * @param tokenSecret
	 */
	//http://localhost:8080/OSN/rest/service/addTwitter/manuel.palacin@upf.edu/s3cr3t/1309971764895000/CArlLtcnCTFOA4mxzdvrdw/OLMzwB37CJuKjv6t2snsfZIJDIsOdytONvmtqC6CoMY/328926660-FoRkNLTpGd7Ka9GdLltMJuxzdiTydhA1F4pcIKWZ/Y6PIY34La28N4smRfTr1qRZnJWpyGmggPYOrvaw
	@GET
	@Path("/addTwitter/{mail}/{userPassword}/{idOSNService}/{consumerKey}/{consumerSecret}/{token}/{tokenSecret}")
	public Message addTwitter(
			@PathParam("mail")String mail, @PathParam("userPassword")String userPassword,
			@PathParam("idOSNService")String idOSNService, 
			@PathParam("consumerKey")String consumerKey,
			@PathParam("consumerSecret")String consumerSecret, 
			@PathParam("token")String token, 
			@PathParam("tokenSecret")String tokenSecret){
		if (userService.loginUser(mail, userPassword).getContent().equals("true")){
			serviceManager.addTwitter(idOSNService, 
					consumerKey, consumerSecret, 
					token, tokenSecret);
			return createMessage("Service activated to use Twitter");
		}else {
			return createMessage("Please register into the system");
		}
	}
	
	/**
	 * Service login service method
	 * 
	 * @param idOSNService
	 * @param servicePassword
	 * @return
	 */
	//http://localhost:8080/OSN/rest/service/loginService/1309971764895000/s3cr3t
	@GET
	@Path("/loginService/{idOSNService}/{servicePassword}")
	public Message loginService(@PathParam("idOSNService")String idOSNService,@PathParam("servicePassword")String servicePassword ){	
		
		return createMessage(String.valueOf( serviceManager.loginService(idOSNService, servicePassword)));
	}
	
	
	public Message createMessage(String content){
		
		Message message = objectFactory.createMessage();
		message.setContent(content);
		return message;
	}
	
	@GET
	@Path("/getServiceJson")
	public edu.upf.opencities.datamodel.Service getServiceJson(){
		edu.upf.opencities.datamodel.Service service = new edu.upf.opencities.datamodel.Service();
		service.setId("TempService123456789");
		service.setName("Temperature Service");
		service.setDescription("This sensor tells everybody the temperature of the Labs Room");
		service.getTags().add("hot");
		service.getTags().add("cold");
		service.setAuthor("UPF Weather Department");
		service.setEmail("weather@upf.edu");
		Resource res1 = new Resource();
		res1.setDescription("REST End Point");
		res1.setFormat("application/xml");
		res1.setUrl("http://opencities/osn/services/TempService123456789/getEntries");
		Resource res2 = new Resource();
		res2.setDescription("Twitter Account");
		res2.setFormat("application/html");
		res2.setUrl("http://twitter.com/@TempService123456789");
		service.getResources().add(res1);
		service.getResources().add(res2);
		service.setUpdatePeriod("15 min");
		service.setLicense("cc-by");
		service.setUrl("http://opencities/osn/services/TempService123456789");
		Extras extras = new Extras();
		extras.setGeographicalGranularity("meters");
		extras.setTemporalCoverageFrom("Monday");
		service.setExtras(extras);
		
		Entry entry1 = new Entry();
		entry1.setId("12123131");
		entry1.setValue("21 degrees");
		service.getEntries().add(entry1);
		
		Entry entry2 = new Entry();
		entry2.setId("12123132");
		entry2.setValue("22 degrees");
		service.getEntries().add(entry2);
		
		return service;
	}
	
}
